# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import List
from fastapi import Request, HTTPException
from sqlalchemy.exc import OperationalError
from sqlalchemy import update, delete, select, func, text
from typing import Generic
from app.entity.system import SysDictType, SysDictData, CreateSysDictType, UpdateSysDictType
from core.curd import PageInfo, CRUDBase, ModelType, IBaseDao, QueryWrapper


class SysDictTypeDao(IBaseDao, Generic[ModelType]):
    """
    测试模块服务层
    """

    def __init__(self, req: Request, model: ModelType):
        self.base = CRUDBase(SysDictType)
        self.model = model
        self.db_session = req.app.state.db_async_session

    async def select_by_query(self, queryWrapper: QueryWrapper) -> SysDictType | None:
        async with self.db_session() as db:
            try:
                rs = await db.execute(select(SysDictType).filter_by(**queryWrapper.gen_where()))
                return rs.scalars().first()

            except OperationalError as e:
                raise HTTPException(status_code=500, detail='数据库服务连接失败!')
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e))
            finally:
                await db.close()

    async def get_sql_data(self, sql: str):
        async with self.db_session() as db:
            try:
                rs = await db.execute(text(sql))
                rows = rs.fetchall()
                rows = list(map(lambda x: {"dict_value": x[0], "dict_label": x[1]}, rows))
                total = len(rows)
                return total, rows
            except OperationalError as e:
                raise HTTPException(status_code=500, detail='数据库服务连接失败!')
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e))
            finally:
                await db.close()

    async def delete_dict_type(self, ids:List[int]):
        async with self.db_session() as db:
            try:
                r1 = await db.execute(delete(SysDictType).where(SysDictType.id.in_(ids)))
                r2 = await db.execute(delete(SysDictData).where(SysDictData.dict_type_id.in_(ids)))
            except OperationalError as e:
                raise HTTPException(status_code=500, detail='数据库服务连接失败!')
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e))
            finally:
                await db.commit()
                await db.close()

    async def get_all_dict_type(self):
        async with self.db_session() as db:
            try:
                result = []
                re = await db.execute(select(SysDictType))
                for r in re.scalars():
                    one = {"dictType":r.dict_type, "dictList":[]}
                    if r.dict_source==0:
                        # 来自字典
                        re = await db.execute(select(SysDictData).filter(SysDictData.dict_type_id==r.id))
                        for d in re.scalars():
                            one["dictList"].append({"dictLabel":d.dict_label, "dictValue":d.dict_value, "labelClass":d.label_class})
                    else:
                        # 来自SQL
                        pass
                    result.append(one)
                return result
            except OperationalError as e:
                raise HTTPException(status_code=500, detail='数据库服务连接失败!')
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e))
            finally:
                await db.close()
    @classmethod
    async def instance(cls, req: Request, model: ModelType):
        return cls(req, model)


class SysDictDataDao(IBaseDao, Generic[ModelType]):
    """
    测试模块服务层
    """

    def __init__(self, req: Request, model: ModelType):
        self.base = CRUDBase(SysDictData)
        self.db_session = req.app.state.db_async_session

    @classmethod
    async def instance(cls, req: Request, model: ModelType):
        return cls(req, model)
